#include "tthreadpool.h"
namespace tlib
{
	TThreadPool::TThreadPool() :running_(false)
	{

	}

	TThreadPool::~TThreadPool()
	{
		if (running_) Stop();
	}

	void TThreadPool::runInThread()
	{
		while (running_)
		{
			TTask task(Take());
			if (task) task();
		}
	}

	void TThreadPool::Start(int numThreads)
	{
		running_ = true;
		for (int i = 0; i < numThreads; i++)
		{
			threads_.push_back(std::thread(std::bind(&TThreadPool::runInThread, this)));
		}
	}

	void TThreadPool::Stop()
	{
		{
			std::lock_guard<std::mutex> lock(mutex_);
			running_ = false;
			notempty_.notify_all();
		}
		for_each(threads_.begin(), threads_.end(), std::bind(&std::thread::join, std::placeholders::_1));
	}

	void TThreadPool::Run(const TTask& tk)
	{
		std::lock_guard<std::mutex> lock(mutex_);
		queue_.push_back(move(tk));
		notempty_.notify_one();
	}

	void TThreadPool::Run(TTask&& tk)
	{
		std::lock_guard<std::mutex> lock(mutex_);
		queue_.push_back(move(tk));
		notempty_.notify_one();
	}

	TTask TThreadPool::Take()
	{
		std::unique_lock<std::mutex> lock(mutex_);
		while (queue_.empty() && running_)
		{
			notempty_.wait(lock);
		}
		TTask task;
		if (!queue_.empty())
		{
			task = queue_.front();
			queue_.pop_front();
		}
		return task;

	}
}